package org.jpro.common.jpa.specification;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.From;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

/**
 * <P>功能描述 : </P>
 * <P>Method Name : EqualSpecification </P>
 * <P>Author : 王泽浩 </P>
 * <P>E-Mail : 1028625100@qq.com </P>
 * <P>Date : 2017-03-14 15:45:17</P>
 * @param <T> the type parameter
 * @since 1.0
 */
public class EqualSpecification<T> extends AbstractSpecification<T> {

    /**
     * The Property.
     */
    private final String property;

    /**
     * The Values.
     */
    private final Object[] values;

    /**
     * <P>功能描述 : </P>
     * <P>Method Name : Equal specification </P>
     * <P>Author : 王泽浩 </P>
     * <P>E-Mail : 1028625100@qq.com </P>
     * <P>Date : 2017-03-14 15:45:17</P>
     * @param property the property
     * @param values the values
     * @since 1.0
     */
    public EqualSpecification(String property, Object... values) {
        this.property = property;
        this.values = values;
    }

    /**
     * <P>功能描述 : </P>
     * <P>Method Name : toPredicate </P>
     * <P>Author : 王泽浩 </P>
     * <P>E-Mail : 1028625100@qq.com </P>
     * <P>Date : 2017-03-14 15:45:18</P>
     * @param root the root
     * @param query the query
     * @param cb the cb
     * @return the predicate
     * @since 1.0
     */
    @Override
    public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
        From from = getRoot(property, root);
        String field = getProperty(property);
        if (values == null) {
            return cb.isNull(from.get(field));
        }
        if (values.length == 1) {
            return getPredicate(from, cb, values[0], field);
        }

        Predicate[] predicates = new Predicate[values.length];
        for (int i = 0; i < values.length; i++) {
            predicates[i] = getPredicate(root, cb, values[i], field);
        }
        return cb.or(predicates);
    }

    /**
     * Gets predicate.
     * @param root the root
     * @param cb the cb
     * @param value the value
     * @param field the field
     * @return the predicate
     */
    private Predicate getPredicate(From root, CriteriaBuilder cb, Object value, String field) {
        return value == null ? cb.isNull(root.get(field)) : cb.equal(root.get(field), value);
    }

}
